<template>
  <base-map ref="GisMap" class="command-dispatching" v-bind="mapConfig" :map-options="mapOption" @ready="onMapReady">
    <template #default="{ AMap, map }">
      <map-polygon :AMap="AMap" :map="map" :auto-district-search="false" />
      <source-board
        v-model="dispatchData"
        :AMap="AMap"
        :people-list="peopleList"
        :entity-list="entityList"
        class="flex-auto-height"
      />
      <map-dispatcher ref="MapDispatcher" v-model="dispatchData" :map="map" :AMap="AMap" />
      <map-command-dispatching-filter
        ref="MapFilter"
        class="map-filter flex-fixed"
        :marker-legends="markerLegends"
        :area-controller="false"
        :community-controller="false"
        :grid-controller="false"
        @filter="onFilter"
      />
    </template>
  </base-map>
</template>

<script>
import BaseMap from '@gis/lib/components/AMap/index.vue';
// import BaseWarnMap from '../../components/amap/map-core-normal.vue';
import SourceBoard from './components/source-board.vue';
import MapDispatcher from './components/map-dispatcher.vue';
import MapPolygon from './components/map-polygon.js';
import MapCommandDispatchingFilter from './components/map-filter.vue';
import openWuZiDialog from './components/wu_zi_chu_bei/index.js';
import Gzsb from '../../components/gis-map/map-marker/js/gzsb.js';
import Cl from '../../components/gis-map/map-marker/js/cl.js';
import { MarkerLayer } from '@gis/lib/components/AMap/js/MarkerLayer.js';
import { getLngLat } from '@gis/lib/components/AMap/js/AMapUtils.js';
import { useUserInfoStore } from '@gis/lib/pinia/userInfo.js';
import { getGisEntityList, getOnlinePeoples } from '@gis/lib/api';
import { bdToGd } from '../../components/gis-map/js/translator.js';
import uniq from 'lodash-es/uniq.js';
import Cyspzy from '../../components/gis-map/map-marker/js/cyspzy.js';

const icon = {
  people: new URL('./assets/map_bt_wgy.png', import.meta.url).href,
  wu_zi: new URL('./assets/map_bt_shebei.png', import.meta.url).href,
};
const defaultStyle = 'amap://styles/cfd800a417c5e6683065b909ce2cee62';

export default {
  name: 'command-dispatching',
  components: {
    BaseMap,
    // BaseWarnMap,
    MapCommandDispatchingFilter,
    MapPolygon,
    MapDispatcher,
    SourceBoard,
  },
  props: {
    mapConfigs: { type: Object, default: undefined },
    mapOptions: { type: Object, default: undefined },
    center: { type: Object, default: undefined },
    useXLGC: Boolean,
    useEntity: { type: Boolean, default: true },
    useInstanceCameras: { type: Boolean, default: true },
    useVideo: { type: Boolean, default: false }, // 视频资源
  },
  data() {
    return {
      range: 100,
      peopleList: [],
      entityList: [],
      markerLegends: [],
      dispatchData: {},
    };
  },
  computed: {
    mapConfig() {
      const opt = {
        useNormal: true,
        useFrame: false,
        useV2Map: false,
        singleMode: false,
      };
      return Object.assign(opt, this.mapConfigs);
    },
    mapOption() {
      const opt = {
        // mapStyle: this.mapStyleKey,
        // gray dark blue darkblue
        mapStyle: 'amap://styles/grey',
        features: ['bg', 'road'],
        viewMode: '2D',
        zoom: 9,
      };
      return Object.assign(opt, this.mapOptions);
    },
    area_code() {
      const { area_code } = useUserInfoStore();
      return area_code;
    },
  },
  created() {
    this.markerLegends = [];
    this.peopleMarkers = [];
    this.entityMarkers = [];
    this.sourceMarkers = {};
    this.videoIns = [];
  },
  mounted() {},
  unmounted() {
    if (this.markerLayer) {
      this.markerLayer.destroy();
      this.markerLayer = null;
    }
  },
  beforeDestroy() {
    if (this.markerLayer) {
      this.markerLayer.destroy();
      this.markerLayer = null;
    }
  },
  methods: {
    onMapReady({ map, AMap }) {
      // console.log(map, AMap, '地图初始化');
      this.map = map;
      this.AMap = AMap;
      this.markerLayer = new MarkerLayer(this.map);
      this.$watch('area_code', this.getDataAsync, { immediate: true });
    },
    getDataAsync() {
      this.getOnlinePeople();
      if (this.useEntity) {
        this.getEntityListAsync();
      }
      if (this.useInstanceCameras) {
        this.getInstanceCameras();
      }
      if (this.useVideo) {
        this.getVideoListAsync();
      }
    },
    async getOnlinePeople() {
      if (!this.area_code) return;
      const params = { area_code: this.area_code };
      const res = await getOnlinePeoples(params);
      this.peopleList = res ? res.data || [] : [];
      this.markerLegends = uniq(this.markerLegends.concat(['online_ry']));
      this.peopleMarkers = this.createMarkers(this.peopleList, {
        icon: icon.people,
      });
    },
    async getEntityListAsync() {
      if (!this.area_code) return;
      const params = { area_code: this.area_code, type_code: "'2_07'" };
      const res = await getGisEntityList(params);
      this.entityList = res ? res.data || [] : [];
      this.markerLegends = uniq(this.markerLegends.concat(['wu_zi_chu_bei']));
      this.entityMarkers = this.createMarkers(this.entityList, {
        icon: icon.wu_zi,
        onClick: (e) => {
          const data = e.target.getExtData();
          openWuZiDialog(data);
        },
      });
    },
    async getVideoListAsync() {
      let videos = await this.getMarkerIns('videos', Cyspzy);
      this.videoIns = videos;
      this.markerLegends = uniq(this.markerLegends.concat(['cyspzy']));
      const layer = await this.markerLayer.getLayer();
      layer.addMarkers([].concat(videos.map((ins) => ins.getMarker())));
    },
    async getMarkerIns(name, Class) {
      const ins = (this[name] = new Class({ map: this.map }));
      await ins.ready();
      return ins.getMarkers();
    },
    getMarkerFromIns(insArr) {
      return insArr.reduce((res, ins) => {
        const type = ins.type;
        if (!Array.isArray(res[type])) {
          res[type] = [];
        }
        res[type].push(ins.getMarker());
        return res;
      }, {});
    },
    async getInstanceCameras() {
      let devices = await this.getMarkerIns('devices', Gzsb);
      let cars = await this.getMarkerIns('cars', Cl);
      // 返回的 - 扎点数组
      if (this.useXLGC !== true) {
        devices = devices.filter((ins) => ins.type !== 'xlgc');
      }
      this.markerLegends = uniq(
        this.markerLegends.concat(
          devices.map((ins) => ins.type),
          cars.map((ins) => ins.type)
        )
      ).filter(Boolean);

      this.sourceMarkers = Object.assign({}, this.getMarkerFromIns(devices), this.getMarkerFromIns(cars));
      const layer = await this.markerLayer.getLayer();
      layer.addMarkers(
        [].concat(
          devices.map((ins) => ins.getMarker()),
          cars.map((ins) => ins.getMarker())
        )
      );
    },
    createMarkers(data, options) {
      if (!data || !data.length) {
        return [];
      }
      options = Object.assign({}, options);
      return data
        .map((item) => {
          const { lng, lat } = getLngLat(item);
          const lngLat = bdToGd(lng, lat);
          if (!lngLat) {
            return null;
          }
          const configData = {
            map: this.map,
            position: lngLat,
            title: item.name,
            label: {
              content: item.name,
              direction: 'top',
              offset: this.AMap ? new this.AMap.Pixel(0, 0) : new AMap.Pixel(0, 0),
            },
            extData: item,
            content: `<img src="${options.icon}" style="width: 38px;height: 56px;" />`,
            offset: this.AMap ? new this.AMap.Pixel(-19, -56) : new AMap.Pixel(-19, -56),
          };
          const marker = this.AMap ? new this.AMap.Marker(configData) : new AMap.Marker(configData);
          if (typeof options.onClick === 'function') {
            marker.on('click', options.onClick);
          }
          return marker;
        })
        .filter(Boolean);
    },
    onFilter(filterData) {
      /* filterData: [{ node:"", leaf:[] }] */
      if (!filterData || !filterData.length) return;
      filterData.forEach(async ({ node, leaf }) => {
        const map = leaf.length ? this.map : null;
        if (node === 'online_ry') {
          this.peopleMarkers.forEach((marker) => marker.setMap(map));
        } else if (node === 'wu_zi_chu_bei') {
          this.entityMarkers.forEach((marker) => marker.setMap(map));
        } else if (node === 'cyspzy') {
          const layer = await this.markerLayer.getLayer();
          const { leaf = [] } = filterData[0];

          const removes = [];
          const adds = [];

          this.videoIns.forEach((insItem) => {
            if (leaf.indexOf(insItem.type) < 0) {
              removes.push(insItem.getMarker());
            } else {
              adds.push(insItem.getMarker());
            }
          });
          layer.removeMarkers(removes);
          layer.addMarkers(adds);
        } else if (this.sourceMarkers[node]) {
          const layer = await this.markerLayer.getLayer();
          const markers = this.sourceMarkers[node];
          leaf.length ? layer.addMarkers(markers) : layer.removeMarkers(markers);
        }
      });
    },
  },
};
</script>

<style scoped lang="less">
.command-dispatching {
  position: relative;
  height: 100%;
  overflow: hidden;
  :deep(.amap-marker),
  .amap-marker {
    .amap-marker-label {
      background: rgba(0, 0, 0, 0.5);
    }
  }
  .source-board {
    position: absolute;
    top: 20px;
    right: 20px;
    bottom: 20px;
  }
  .map-filter {
    border: 1px solid;
    border-image: linear-gradient(0deg, #0085b7, #0081a0) 10 10;
    background: linear-gradient(0deg, #072c3c 0%, rgba(0, 24, 47, 0.4) 100%);
    box-shadow: 0px 0px 6px 0px rgba(1, 1, 1, 0.35);
    position: absolute;
    left: 20px;
    bottom: 20px;
    z-index: 11;
    max-width: 220px;
  }
}
</style>
